import { expect, it, describe } from "vitest"
import {
    TickFormattingOptions,
    OwidVariableRoundingMode,
} from "@ourworldindata/types"
import { formatValue } from "./formatValue"

describe("rounding to a fixed number of decimals", () => {
    // prettier-ignore
    const cases: [string, number, string, TickFormattingOptions][] = [
        ["default", 1, "1", {}],
        ["default negative", -1, "-1", {}],
        ["default small", 0.001, "<0.01", {}],
        ["default million specific", 1_179_766, "1.18 million", {}],
        ["default billion specific", 1_234_567_890, "1.23 billion", {}],
        ["default 10 billion specific", 12_345_678_901, "12.35 billion", {}],
        ["default billion with rounding", 1_239_999_999, "1.24 billion", {}],
        ["default small", 0.0000000001, "<0.01", {}],
        ["thousand", 1000, "1,000", {}],
        ["thousand rounding", 1002, "1,002", {}],
        ["ten thousand", 10000, "10,000", {}],
        ["hundred thousand default", 100_000, "100,000", {}],
        ["hundred thousand specific default", 123_456, "123,456", {}],
        ["hundred thousand rounding default", 12_388, "12,388", {}],
        ["hundred thousand specific decimals", 123_456.789, "123,456.79", {}],
        ["999999 specific default", 999_999.99, "999,999.99", {}],
        // TODO: should round to '1 million' but returns '1,000,000'
        // ["999999 rounding default", 999999.999, "1 million", {}],
        ["million", 1_000_000, "1 million", {}],
        ["billion", 1_000_000_000, "1 billion", {}],
        ["trillion", 1_000_000_000_000, "1 trillion", {}],
        ["quadrillion", 1_000_000_000_000_000, "1 quadrillion", {}],
        ["negative million", -1_000_000, "-1 million", {}],
        ["negative billion", -1_000_000_000, "-1 billion", {}],
        ["negative trillion", -1_000_000_000_000, "-1 trillion", {}],
        ["negative quadrillion", -1_000_000_000_000_000, "-1 quadrillion", {}],
        ["1000 short prefix", 1000, "1k", { numberAbbreviation: "short" }],
        ["1499 short prefix", 1499, "1.5k", { numberAbbreviation: "short" }],
        ["1001 short prefix", 1001, "1k", { numberAbbreviation: "short" }],
        ["1009 short prefix", 1009, "1.01k", { numberAbbreviation: "short" }],
        ["12345 short prefix", 12_345, "12.35k", { numberAbbreviation: "short" }],
        ["123456 short prefix", 123_456, "123.46k", { numberAbbreviation: "short" }],
        ["123456 decimal short prefix", 98_712.78901, "98.71k", { numberAbbreviation: "short", numDecimalPlaces: 10 }],
        ["hundred thousand short prefix decimal", 100_000.44, "100k", { numberAbbreviation: "short" }],
        ["1000 long prefix", 1000, "1,000", { numberAbbreviation: "long" }],
        ["1499 long prefix", 1499, "1,499", { numberAbbreviation: "long" }],
        ["1001 long prefix", 1001, "1,001", { numberAbbreviation: "long" }],
        ["1009 long prefix", 1009, "1,009", { numberAbbreviation: "long" }],
        ["ten thousand long prefix", 10_000, "10,000", { numberAbbreviation: "long" }],
        ["hundred thousand long prefix", 100_000, "100,000", { numberAbbreviation: "long" }],
        ["hundred thousand long prefix decimal", 100_000.44, "100,000.44", { numberAbbreviation: "long" }],
        ["million short prefix", 1_000_000, "1M", { numberAbbreviation: "short" }],
        ["billion short prefix", 1_000_000_000, "1B", { numberAbbreviation: "short" }],
        ["trillion short prefix", 1_000_000_000_000, "1T", { numberAbbreviation: "short" }],
        ["quadrillion short prefix", 1_000_000_000_000_000, "1quad", { numberAbbreviation: "short" }],
        ["2 decimals with integer", 1, "1", { numDecimalPlaces: 2 }],
        ["2 decimals with float", 1.123, "1.12", { numDecimalPlaces: 2 }],
        ["4 decimals with float", 1.123, "1.123", { numDecimalPlaces: 4 }],
        ["0 decimals with abbreviation", 1_234_567, "1.23 million", { numDecimalPlaces: 0, numberAbbreviation: "long" }],
        ["1 decimal with abbreviation", 1_234_567, "1.23 million", { numDecimalPlaces: 1, numberAbbreviation: "long" }],
        ["1 decimal with short abbreviation", 1234, "1.23k", { numDecimalPlaces: 1, numberAbbreviation: "short" }],
        ["2 decimal with percentage", 19.985, "19.98%", { numDecimalPlaces: 2, unit: "%" }],
        ["with unit", 1, "$1", { unit: "$" }],
        ["with custom unit", 1, "1pp", { unit: "pp", spaceBeforeUnit: false }],
        ["with custom unit and space", 1, "1 pp", { unit: "pp", spaceBeforeUnit: true }],
        ["negative with unit", -1, "-$1", { unit: "$" }],
        ["trailingZeroes true", 1.10, "1.1", { trailingZeroes: false }],
        ["trailingZeroes false", 1.10, "1.10", { trailingZeroes: true }],
        ["$ spaceBeforeUnit false", 1.1, "$1.1", { spaceBeforeUnit: false, unit: "$" }],
        ["$ spaceBeforeUnit true", 1.1, "$1.1", { spaceBeforeUnit: true, unit: "$" }],
        ["% spaceBeforeUnit true", 1.1, "1.1 %", { spaceBeforeUnit: true, unit: "%" }],
        ["% spaceBeforeUnit false", 1.1, "1.1%", { spaceBeforeUnit: false, unit: "%" }],
        ["% small", 0.1, "0.1%", { unit: "%" }],
        ["% very small", 0.001, "<0.01%", { unit: "%" }],
        ["$ very small", 0.001, "<$0.01", { unit: "$" }],
        ["%compound spaceBeforeUnit false", 1.1, "1.1%compound", { spaceBeforeUnit: false, unit: "%compound" }],
        ["numberAbbreviation long", 1_000_000_000, "1 billion", { numberAbbreviation: "long" }],
        ["numberAbbreviation million specific", 846_691_846.8, "846.69 million", { numberAbbreviation: "long" }],
        ["numberAbbreviation billion specific", 123_456_789_012, "123.46 billion", { numberAbbreviation: "long" }],
        ["numberAbbreviation long with unit", 1_000_000_000, "$1 billion", { numberAbbreviation: "long", unit: "$" }],
        ["numberAbbreviation short", 1_000_000_000, "1B", { numberAbbreviation: "short" }],
        ["numberAbbreviation %", 20_000, "20,000%", { numberAbbreviation: "short", unit: "%" }],
        ["numberAbbreviation false", 1_000_000_000, "1,000,000,000", { numberAbbreviation: false }],
        ["numberAbbreviation false very small", 0.000000001, "0.000000001", { numberAbbreviation: false, numDecimalPlaces: 10 }],
        ["showPlus true", 1, "+1", { showPlus: true }],
        ["showPlus false", 1, "1", { showPlus: false }],
        ["showPlus false with negative number", -1, "-1", { showPlus: false }],
        ["showPlus true with unit", 1, "+$1", { showPlus: true, unit: "$" }],
        ["showPlus true with % and 4 decimals", 1.23456, "+1.2346%", { showPlus: true, numDecimalPlaces: 4, unit: "%" }],
        ["showPlus false with $ and trailingZeroes false", 1234.5678, "$1,234.57", { showPlus: false, unit: "$", trailingZeroes: false }],
        ["showPlus false with $, trailingZeroes true, and spaceBeforeUnit true", 1234.5678, "$1,234.57", { showPlus: false, unit: "$", trailingZeroes: true, spaceBeforeUnit: true }],
        ["showPlus true with $, trailingZeroes true, and spaceBeforeUnit true", 1234.5678, "+$1,234.57", { showPlus: true, unit: "$", trailingZeroes: true, spaceBeforeUnit: true }],
    ]
    cases.forEach(([description, input, output, options]) => {
        it(description, () => {
            expect(formatValue(input, options)).toBe(output)
        })
    })
})

describe("rounding to significant figures", () => {
    // prettier-ignore
    const cases: [string, number, string, TickFormattingOptions][] = [
        ["default", 1, "1.00", {}],
        ["default negative", -1, "-1.00", {}],
        ["default small", 0.001, "0.00100", {}],
        ["default very small", 0.0000000001, "0.000000000100", {}],
        ["default million specific", 1_179_766, "1.18 million", {}],
        ["default billion specific", 1_234_567_890, "1.23 billion", {}],
        ["default 10 billion specific", 12_345_678_901, "12.3 billion", {}],
        ["default billion with rounding", 1_239_999_999, "1.24 billion", {}],
        ["thousand", 1000, "1,000", {}],
        ["thousand rounding", 1234, "1,230", {}],
        ["ten thousand", 10_000, "10,000", {}],
        ["hundred thousand default", 100_000, "100,000", {}],
        ["hundred thousand specific default", 123_456, "123,000", {}],
        ["hundred thousand rounding default", 12_388, "12,400", {}],
        ["hundred thousand specific decimals", 123_456.789, "123,000", {}],
        // TODO: should round to '1.00 million' but returns '1,000,000'
        // ["999999 specific default", 999999, "1.00 million", {}],
        ["million", 1_000_000, "1.00 million", {}],
        ["billion", 1_000_000_000, "1.00 billion", {}],
        ["trillion", 1_000_000_000_000, "1.00 trillion", {}],
        ["quadrillion", 1_000_000_000_000_000, "1.00 quadrillion", {}],
        ["negative million", -1_000_000, "-1.00 million", {}],
        ["negative billion", -1_000_000_000, "-1.00 billion", {}],
        ["negative trillion", -1_000_000_000_000, "-1.00 trillion", {}],
        ["negative quadrillion", -1_000_000_000_000_000, "-1.00 quadrillion", {}],
        ["1000 short prefix", 1000, "1.00k", { numberAbbreviation: "short" }],
        ["1499 short prefix", 1499, "1.50k", { numberAbbreviation: "short" }],
        ["1001 short prefix", 1001, "1.00k", { numberAbbreviation: "short" }],
        ["1009 short prefix", 1009, "1.01k", { numberAbbreviation: "short" }],
        ["12345 short prefix", 12_345, "12.3k", { numberAbbreviation: "short" }],
        ["123456 short prefix", 123_456, "123k", { numberAbbreviation: "short" }],
        ["hundred thousand short prefix decimal", 100_000.44, "100k", { numberAbbreviation: "short" }],
        ["1000 long prefix", 1000, "1,000", { numberAbbreviation: "long" }],
        ["1499 long prefix", 1499, "1,500", { numberAbbreviation: "long" }],
        ["1001 long prefix", 1001, "1,000", { numberAbbreviation: "long" }],
        ["1009 long prefix", 1009, "1,010", { numberAbbreviation: "long" }],
        ["ten thousand long prefix", 10000, "10,000", { numberAbbreviation: "long" }],
        ["hundred thousand long prefix", 100_000, "100,000", { numberAbbreviation: "long" }],
        ["hundred thousand long prefix decimal", 100_000.44, "100,000", { numberAbbreviation: "long" }],
        ["million short prefix", 1_000_000, "1.00M", { numberAbbreviation: "short" }],
        ["billion short prefix", 1_000_000_000, "1.00B", { numberAbbreviation: "short" }],
        ["trillion short prefix", 1_000_000_000_000, "1.00T", { numberAbbreviation: "short" }],
        ["quadrillion short prefix", 1_000_000_000_000_000, "1.00quad", { numberAbbreviation: "short" }],
        ["1 with 1 significant figure", 1, "1", { numSignificantFigures: 1 }],
        ["1 with 2 significant figures", 1, "1.0", { numSignificantFigures: 2 }],
        ["1 with 3 significant figures", 1, "1.00", { numSignificantFigures: 3 }],
        ["0.999 with 1 significant figure", 0.999, "1", { numSignificantFigures: 1 }],
        ["0.999 with 2 significant figures", 0.999, "1.0", { numSignificantFigures: 2 }],
        ["0.999 with 3 significant figures", 0.999, "0.999", { numSignificantFigures: 3 }],
        ["0.999 with 4 significant figures", 0.999, "0.9990", { numSignificantFigures: 4 }],
        // TODO: should round to '20.0' but returns '19.95'
        // ["19.95 with 4 significant figures", 19.95, "20.0", {numSignificantFigures: 3}],
        ["1234 with 1 significant figure", 1234, "1,000", { numSignificantFigures: 1 }],
        ["1234 with 2 significant figures", 1234, "1,200", { numSignificantFigures: 2 }],
        ["1234 with 3 significant figures", 1234, "1,230", { numSignificantFigures: 3 }],
        ["1234 with 4 significant figures", 1234, "1,234", { numSignificantFigures: 4 }],
        ["1234 with 5 significant figures", 1234, "1,234.0", { numSignificantFigures: 5 }],
        ["1234 with 6 significant figures", 1234, "1,234.00", { numSignificantFigures: 6 }],
        ["0.0012 with 1 significant figure", 0.0012, '0.001', {numSignificantFigures: 1}],
        ["0.0012 with 2 significant figures", 0.0012, '0.0012', {numSignificantFigures: 2}],
        ["0.0012 with 3 significant figures", 0.0012, '0.00120', {numSignificantFigures: 3}],
        ["2 significant figures with abbreviation", 1_234_567, "1.2 million", { numSignificantFigures: 2, numberAbbreviation: "long" }],
        ["3 significant figures with abbreviation", 1_234_567, "1.23 million", { numSignificantFigures: 3, numberAbbreviation: "long" }],
        ["2 significant figures with short abbreviation", 1234, "1.2k", { numSignificantFigures: 2, numberAbbreviation: "short" }],
        ["3 significant figures with percentage", 19.986, "20.0%", { numSignificantFigures: 3, unit: "%" }],
        ["4 significant figures with percentage", 19.986, "19.99%", { numSignificantFigures: 4, unit: "%" }],
        ["with unit", 1, "$1.00", { unit: "$" }],
        ["with custom unit", 1, "1.00pp", { unit: "pp", spaceBeforeUnit: false }],
        ["with custom unit and space", 1, "1.00 pp", { unit: "pp", spaceBeforeUnit: true }],
        ["negative with unit", -1, "-$1.00", { unit: "$" }],
        ["trailingZeroes true", 1.10, "1.10", { trailingZeroes: false }], // trailingZeroes is ignored
        ["trailingZeroes false", 1.10, "1.10", { trailingZeroes: true }], // trailingZeroes is ignored
        ["$ spaceBeforeUnit false", 1.1, "$1.10", { spaceBeforeUnit: false, unit: "$" }],
        ["$ spaceBeforeUnit true", 1.1, "$1.10", { spaceBeforeUnit: true, unit: "$" }],
        ["% spaceBeforeUnit true", 1.1, "1.10 %", { spaceBeforeUnit: true, unit: "%" }],
        ["% spaceBeforeUnit false", 1.1, "1.10%", { spaceBeforeUnit: false, unit: "%" }],
        ["% small", 0.1, "0.100%", { unit: "%" }],
        ["% very small", 0.001, "0.00100%", { unit: "%" }],
        ["%compound spaceBeforeUnit false", 1.1, "1.10%compound", { spaceBeforeUnit: false, unit: "%compound" }],
        ["numberAbbreviation long", 1_000_000_000, "1.00 billion", { numberAbbreviation: "long" }],
        ["numberAbbreviation million specific", 846_691_846.8, "847 million", { numberAbbreviation: "long" }],
        ["numberAbbreviation billion specific", 123_456_789_012, "123 billion", { numberAbbreviation: "long" }],
        ["numberAbbreviation long with unit", 1_000_000_000, "$1.00 billion", { numberAbbreviation: "long", unit: "$" }],
        ["numberAbbreviation short", 1_000_000_000, "1.00B", { numberAbbreviation: "short" }],
        ["numberAbbreviation %", 20_000, "20,000%", { numberAbbreviation: "short", unit: "%" }],
        ["numberAbbreviation false", 1_000_000_000, "1,000,000,000", { numberAbbreviation: false }],
        ["numberAbbreviation false very small", 0.000000001, "0.000000001", { numberAbbreviation: false, numSignificantFigures: 1 }],
        ["showPlus true", 1, "+1.00", { showPlus: true }],
        ["showPlus false", 1, "1.00", { showPlus: false }],
        ["showPlus false with negative number", -1, "-1.00", { showPlus: false }],
        ["showPlus true with unit", 1, "+$1.00", { showPlus: true, unit: "$" }],
        ["showPlus true with % and 4 significant numbers", 1.23456, "+1.235%", { showPlus: true, unit: "%", numSignificantFigures: 4 }],
    ]
    cases.forEach(([description, input, output, options]) => {
        it(description, () => {
            expect(
                formatValue(input, {
                    ...options,
                    roundingMode: OwidVariableRoundingMode.significantFigures,
                })
            ).toBe(output)
        })
    })
})
